home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / SysMenu 1.4 Folder.sit / SysMenu 1.4 Folder / SysMenu 1.4 / sysmenu.c < prev    next >
C/C++ Source or Header  |  1996-04-20  |  10KB  |  316 lines

  1. // File "sysmenu.c" - Sample shell for creating and installing your own System Menu 
  2. //                    from a system extension.  <fprefect@umich.edu>, 2/26/95
  3. //                    Can be compiled under CW8 as 68k INIT Code Rsrc (System Heap)
  4. //
  5. //    * Modified 4/20/96 (MJS) -    Updated for CW8
  6. //                                Updated enclosed INIT Dispatcher to 1.3
  7. //                                Improved ResError checking
  8. //
  9. //    * Modified 12/5/95 (MJS) -    Rebuilt for CW7 Code Rsrc structure, simplifying and
  10. //                                combining if possible. Same code for 68k and PPC.
  11. //                             -    Fixed A4-global access at end of SystemMenu patch.
  12. //
  13. //    * Modified 7/25/95 (MJS) -    Restructured to work under CW6
  14. //
  15. //    * Modified 3/12/95 (MJS) -    Added InsertMenu patch to support dynamic menu numbering.
  16.  
  17. // * ******************************************************************************* *
  18.  
  19. #include <A4Stuff.h>
  20. #include <Gestalt.h>
  21. #include <Icons.h>
  22. #include <Traps.h>
  23.  
  24. #include "sysmenu.h"
  25. #include "patches.h"
  26.  
  27. //#define ____DEBUG____
  28. #define k68KProcType    '68K・'
  29. #define kPPCProcType    'PPC・'
  30.  
  31. // * ******************************************************************************* *
  32. // Global Declarations
  33.  
  34. GlobalsRec glob;
  35.  
  36. // * ******************************************************************************* *
  37. // * ******************************************************************************* *
  38.  
  39. void main() {
  40.     long saveA4, response;
  41.     Handle myHandle;
  42.     
  43. #ifdef ____DEBUG____
  44.     // Test for the option key - Beep, but dont load
  45.     if ((* (((char *) 0x0174) + 7)) & 0x04) {
  46.         SysBeep(7);
  47.         return;
  48.         }
  49. #endif ____DEBUG____
  50.  
  51.     saveA4 = SetCurrentA4();
  52.  
  53.     // Determine the environment and prepare our code
  54.     if (Gestalt(gestaltSystemVersion, &response) || (response < 0x0700)) goto PROC_END;
  55.     myHandle = Get1Resource((GetCurrentISA() == kPowerPCISA) ?
  56.             kPPCProcType : k68KProcType, 0);
  57.     if (!myHandle || ResError()) goto PROC_END;
  58.     DetachResource(myHandle);
  59.     if (ResError()) goto PROC_END;
  60.  
  61.     // Setup Global Data
  62.     SetZone(SystemZone());
  63.     
  64.     // Setup Handlers
  65.     glob.saveInsertMenu = ApplyTrapPatch(_InsertMenu, 
  66.             (ProcPtr) NewInsertMenuProc(Patched_InsertMenu));
  67.     glob.saveDrawMenuBar = ApplyTrapPatch(_DrawMenuBar,
  68.             (ProcPtr) NewDrawMenuBarProc(Patched_DrawMenuBar));
  69.     glob.saveMenuSelect = ApplyTrapPatch(_MenuSelect,
  70.             (ProcPtr) NewMenuSelectProc(Patched_MenuSelect));
  71.     glob.saveSystemMenu = ApplyTrapPatch(_SystemMenu,
  72.             (ProcPtr) NewSystemMenuProc(Patched_SystemMenu));
  73.  
  74.     glob.mHdl = 0;
  75.     glob.menuID = 0;
  76.     glob.menuIcon = 0;
  77.     glob.sysMenus = (short **) NewHandle(0); 
  78.     
  79.     // Load up our icon suite for the menu "title" (if the iconID is non-zero)
  80.     // Get *all* icons in case the desired size (12x12) isn't available.
  81.     if (kPrefIconID && ! GetIconSuite(&myHandle, kPrefIconID, svAllAvailableData) &&
  82.             ! ForEachIconDo(myHandle, svAllAvailableData, NewIconActionProc(DetachIcons), 0))
  83.         glob.menuIcon = myHandle;
  84.  
  85.     // Remember the location of our home rsrc file, in case we want to 
  86.     // load an dialog or other resource at run-time. Note: this doesn't provide
  87.     // any guarantee that the file will be there later, so check your errors!
  88.     if (CurResFileAsFSSpec(&glob.homeFile)) glob.homeFile.vRefNum = 0;
  89.     
  90.     SetZone(ApplicZone());
  91.  
  92. PROC_END:
  93.     SetA4(saveA4);
  94.     }
  95.  
  96. // * ******************************************************************************* *
  97. // * ******************************************************************************* *
  98.  
  99. short CurResFileAsFSSpec(FSSpec *fileSpec) {
  100.     short i, err=0;
  101.     Str63 textBuff;
  102.     FCBPBRec fcbPB;
  103.     
  104.     for(i=0; i<sizeof(FSSpec); ((char *) fileSpec)[i++]=0);
  105.     
  106.     fcbPB.ioCompletion = 0;
  107.     fcbPB.ioFCBIndx = 0;
  108.     fcbPB.ioVRefNum = 0;
  109.     fcbPB.ioRefNum = CurResFile();
  110.     fcbPB.ioNamePtr = textBuff;
  111.     if (err = PBGetFCBInfoSync(&fcbPB)) return(err);
  112.     
  113.     fileSpec->vRefNum = fcbPB.ioFCBVRefNum;
  114.     fileSpec->parID = fcbPB.ioFCBParID;
  115.     BlockMove(textBuff, fileSpec->name, textBuff[0]+1);
  116.     
  117.     return(err);
  118.     }
  119.  
  120. // * ******************************************************************************* *
  121. // * ******************************************************************************* *
  122.  
  123. ProcPtr ApplyTrapPatch(short trap, ProcPtr patchPtr) {
  124.     ProcPtr trapPtr;
  125.     
  126.     if (! patchPtr) return(0);
  127.  
  128.     trapPtr = (ProcPtr) NGetTrapAddress(trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  129.     NSetTrapAddress((UniversalProcPtr) patchPtr, trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  130.     return(trapPtr);
  131.     }
  132.  
  133. // * ******************************************************************************* *
  134. // * ******************************************************************************* *
  135.  
  136. pascal short DetachIcons(long iconType, Handle *iconHdl, void *data) {
  137.     short err=0;
  138.     
  139.     if (*iconHdl) {
  140.         DetachResource(*iconHdl);
  141.         HNoPurge(*iconHdl);
  142.         err = ResError();
  143.         }
  144.     return(err);
  145.     }
  146.  
  147. // * ******************************************************************************* *
  148. // * ******************************************************************************* *
  149. #pragma mark -
  150.  
  151. pascal void Patched_InsertMenu(MenuHandle mHdl, short beforeID) {
  152.     short menuID = (*mHdl)->menuID;
  153.     long saveA4;
  154.     ProcPtr proc;
  155.     
  156.     saveA4 = SetCurrentA4();
  157.  
  158. #ifdef ____DEBUG____
  159.         Debugger();
  160. #endif ____DEBUG____
  161.  
  162.     // As suggested to me, we need a reliable way to track what menus 
  163.     // have been installed, so we can pick a unique ID for ours. This
  164.     // function simply tracks the ID's to a global variable.
  165.     if (! glob.menuID && glob.sysMenus && (menuID < 0))
  166.         PtrAndHand((Ptr) &menuID, (Handle) glob.sysMenus, sizeof(menuID));
  167.  
  168.     proc = glob.saveInsertMenu;
  169.     SetA4(saveA4);
  170.     CallInsertMenuProc(proc, mHdl, beforeID);
  171.     }
  172.  
  173. // * ******************************************************************************* *
  174. // * ******************************************************************************* *
  175.  
  176. pascal void Patched_DrawMenuBar() {
  177.     short i, found;
  178.     long saveA4;
  179.     ProcPtr proc;
  180.     Str32 textBuff;
  181.     THz saveZone;
  182.     
  183.     saveA4 = SetCurrentA4();
  184.  
  185.     if (! glob.mHdl) {
  186.         // On the first chance, we create and install the new menu 
  187.         // (We need to wait for the Menu Mgr to be initialized to setup)
  188.  
  189. #ifdef ____DEBUG____
  190.         Debugger();
  191. #endif ____DEBUG____
  192.         
  193.         // Let's not create the menu in this App's heap
  194.         saveZone = GetZone();
  195.         SetZone(SystemZone());
  196.  
  197.         // Search for an unused Menu ID, then install the menu. We have tracked
  198.         // the InsertMenu calls, so now we pick an ID not in that list. When done
  199.         // we set the gMenuID and dispose (and clear) the gSysMenus handle.
  200.         for(glob.menuID = kPrefMenuID; ; glob.menuID++) {
  201.             i=GetHandleSize((Handle) glob.sysMenus) / sizeof(**glob.sysMenus);
  202.             for(found = 0; !found && (i>0);
  203.                     found = ((*glob.sysMenus)[--i] == glob.menuID));
  204.             if (! found) {
  205.                 DisposeHandle((Handle) glob.sysMenus);
  206.                 glob.sysMenus = 0;
  207.                 break;
  208.                 }
  209.             } 
  210.             
  211.         // Setup our new menu with its (optional) cool icon
  212.         if (glob.menuIcon) {
  213.             textBuff[0]=5;
  214.             textBuff[1]=1;
  215.             BlockMove(&glob.menuIcon, textBuff+2, sizeof(glob.menuIcon));
  216.             }
  217.           else BlockMove("¥pMenu", textBuff, sizeof("¥pMenu"));
  218.         glob.mHdl = NewMenu(glob.menuID, textBuff);
  219.         
  220.         // For this example, we build it from scratch. I prefer making the
  221.         // AppendMenu() call with dummy args *then* SetItem() with our item.
  222.         // If you trust AppendMenu() with raw data, it will interpret the Menu
  223.         // Managers meta-chars ("-"=Separator, "("=Disabled, "/B"=Command-B, etc)
  224.         AppendMenu(glob.mHdl, "¥p ");
  225.         SetItem(glob.mHdl, CountMItems(glob.mHdl), "¥pAbout SysMenu...");
  226.         AppendMenu(glob.mHdl, "¥p-");
  227.         AppendMenu(glob.mHdl, "¥p ");
  228.         SetItem(glob.mHdl, CountMItems(glob.mHdl), "¥pItem 1");
  229.         AppendMenu(glob.mHdl, "¥p ");
  230.         SetItem(glob.mHdl, CountMItems(glob.mHdl), "¥pItem 2");
  231.         AppendMenu(glob.mHdl, "¥p ");
  232.         SetItem(glob.mHdl, CountMItems(glob.mHdl), "¥pItem 3");
  233.         AppendMenu(glob.mHdl, "¥p ");
  234.         SetItem(glob.mHdl, CountMItems(glob.mHdl), "¥pItem 4");
  235.         
  236.         InsertMenu(glob.mHdl, 0);
  237.         
  238.         SetZone(saveZone); 
  239.         }
  240.     proc = glob.saveDrawMenuBar;
  241.     SetA4(saveA4);
  242.     CallDrawMenuBarProc(proc);
  243.     }
  244.  
  245. // * ******************************************************************************* *
  246. // * ******************************************************************************* *
  247.  
  248. pascal long Patched_MenuSelect(Point where) {
  249.     long saveA4, value;
  250.     ProcPtr proc;
  251.     
  252.     saveA4 = SetCurrentA4();
  253.  
  254. #ifdef ____DEBUG____
  255.         Debugger();
  256. #endif ____DEBUG____
  257.  
  258.     // This function is called when the user first clicks in the menubar.
  259.     // Its an ideal place to update the contents of your menu on the fly
  260.     // to reflect current settings or conditions.
  261.     
  262.     // You should comment out this patch if you dont use the hook.
  263.  
  264.     proc = glob.saveMenuSelect;
  265.     SetA4(saveA4);
  266.     value = CallMenuSelectProc(proc, where);
  267.     return(value);
  268.     }
  269.  
  270. // * ******************************************************************************* *
  271. // * ******************************************************************************* *
  272.  
  273. pascal void Patched_SystemMenu(long result) {
  274.     short menuID, itemID, compareID;
  275.     long saveA4;
  276.     ProcPtr proc;
  277.     
  278.     saveA4 = SetCurrentA4();
  279.  
  280.     menuID = (result & 0xFFFF0000) >> 16;
  281.     itemID = result & 0x0000FFFF;
  282.     compareID = glob.menuID;
  283.  
  284.     // When the user has selected a menu item (by mouse or cmd-key) 
  285.     // we scan the event and handle it if it is from our menu.
  286.     if (menuID == compareID) {
  287.  
  288. #ifdef ____DEBUG____
  289.         Debugger();
  290. #endif ____DEBUG____
  291.  
  292.         // Some apps aren't careful about giving us the arrow.
  293.         InitCursor();
  294.         
  295.         switch(itemID) {
  296.             case 1:
  297.                 SysBeep(7);
  298.                 break;
  299.             default: 
  300.                 SysBeep(7);
  301.                 SysBeep(7);
  302.                 break;
  303.             }
  304.         
  305.         // I don't think this is vital, but may be helpful for handlers
  306.         // that go into a GNE loop (such as Alert() or ModalDialog())
  307.         HiliteMenu(0);
  308.         }
  309.  
  310.     proc = glob.saveSystemMenu;
  311.     SetA4(saveA4);
  312.     // Otherwise, pass it on!
  313.     if (menuID != compareID) CallSystemMenuProc(proc, result);
  314.     }
  315.  
  316.